﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace PackOrders
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        SalesManagerEntities _sme = new SalesManagerEntities();
        private Int32 _packageID;
        private tblInventoryTransaction[] _inventoryTransactions;
        private Int32 _ownerID = -1;
        private bool _closing = false;
        private tblMiscDef[] _miscDefs = null;

        public MainWindow()
        {
            InitializeComponent();
        }

        public static readonly DependencyProperty HasPackageProperty =
            DependencyProperty.Register("HasPackage", typeof(bool), typeof(MainWindow));
        public bool HasPackage
        {
            get { return (bool)GetValue(HasPackageProperty); }
            set 
            { 
                SetValue(HasPackageProperty, value);
                SetValue(HasNoPackageProperty, !value); 
            }
        }

        public static readonly DependencyProperty HasNoPackageProperty =
            DependencyProperty.Register("HasNoPackage", typeof(bool), typeof(MainWindow));
        public bool HasNoPackage
        {
            get { return (bool)GetValue(HasNoPackageProperty); }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            HasPackage = false;
            txtPackageID.Focus();
        }

        private void txtPackageID_LostFocus(object sender, RoutedEventArgs e)
        {
            HasPackage = false;
            if (!Int32.TryParse(txtPackageID.Text, out _packageID))
            {
                if (!_closing)
                {
                    MessageBox.Show("Invalid packageID");
                    txtPackageID.Text = string.Empty;
                    if (e != null)
                        e.Handled = true;
                }
                return;
            }
            _inventoryTransactions = (from c in _sme.tblInventoryTransaction
                    where c.PackageID == _packageID
                        && c.InventoryTransactionTypeCode == "S"
                        && c.InventoryTransactionStatusCode == "P"
                    select c).ToArray();
            if (_inventoryTransactions.Count() == 0)
            {
                if (!_closing)
                {
                    MessageBox.Show("PackageID doesn't match a printed package");
                    txtPackageID.Text = string.Empty;
                    if (e != null)
                        e.Handled = true;
                }
                return;
            }

            gridItems.ItemsSource = _inventoryTransactions;

            // Look up the user defined fields for the InventoryTransactionDetail table.
            if (_ownerID != _inventoryTransactions.First().Inventory.Product.OwnerID)
            {
                _ownerID = _inventoryTransactions.First().Inventory.Product.OwnerID;

                _miscDefs = (from c in _sme.tblMiscDefs
                        where c.TableName.Trim() == "tblInventoryTransactionDetail" &&
                            (c.OwnerID == _ownerID || c.OwnerID == null)
                        select c).ToArray();
            }

            HasPackage = true;
            txtItem.Focus();
        }

        private void txtItem_LostFocus(object sender, RoutedEventArgs e)
        {
            bool productOK = false;
            Int32 productID;
            if (txtItem.Text.Trim() == string.Empty)
            {
                CheckPackage();
                return;
            }
            if (Int32.TryParse(txtItem.Text, out productID))
            {
                tblInventoryTransaction inventoryTransaction = _inventoryTransactions.First(c => c.Inventory.ProductID == productID);
                if (inventoryTransaction != null)
                {
                    if (inventoryTransaction.Added < inventoryTransaction.NegQty)
                    {
                        inventoryTransaction.Added++;
                        productOK = true;
                    }
                }
            }
            if (!productOK)
            {
                if (!_closing)
                {
                    MessageBox.Show("The item entered is not valid or is alreay filled for this order", "Error", MessageBoxButton.OK, MessageBoxImage.Exclamation);
                    txtItem.Text = string.Empty;
                    if (e != null)
                        e.Handled = true;
                }
                return;
            }

            txtItem.Text = string.Empty;
            if (!CheckPackage())
                e.Handled = true;
        }

        private void btnAddItem_Click(object sender, RoutedEventArgs e)
        {
            tblInventoryTransaction inventoryTransaction = (tblInventoryTransaction)gridItems.SelectedItem;
            if (inventoryTransaction != null)
                if (inventoryTransaction.Added < inventoryTransaction.NegQty)
                {
                    inventoryTransaction.Added++;
                    if (inventoryTransaction.Inventory.Product.TrackIndividual)
                    {
                        tblInventoryTransactionDetail newDetail = new tblInventoryTransactionDetail();
                        newDetail.InventoryTransaction = inventoryTransaction;
                        _sme.AddTotblInventoryTransactionDetails(newDetail);

                        //System.Windows.Threading.DispatcherTimer timer = new System.Windows.Threading.DispatcherTimer();
                        //timer.Interval = new TimeSpan(0, 0, 1);
                        //timer.Tick += new EventHandler(timer_Tick);
                        //timer.Start();
                        //DataGrid g = GetDescendantByName((FrameworkElement)gridItems.ItemContainerGenerator.ContainerFromItem(inventoryTransaction), "gridDetails") as DataGrid;
                        //if (g != null)
                        //{
                        //    g.SelectedItem = newDetail;
                        //    g.Focus();
                        //    //g.BeginEdit();
                        //    //List<TextBox> textBoxes = GetChildren<TextBox>((FrameworkElement)g.ItemContainerGenerator.ContainerFromItem(newDetail));
                        //    //if (textBoxes.Count > 0)
                        //    //    textBoxes[0].Focus();
                        //}
                        
                        return;
                    }
                }
            CheckPackage();
            txtItem.Focus();
        }

        //void timer_Tick(object sender, EventArgs e)
        //{
        //    System.Windows.Threading.DispatcherTimer timer = (System.Windows.Threading.DispatcherTimer)sender;
        //    timer.Stop();

        //    DataGrid g = GetDescendantByName((FrameworkElement)gridItems.ItemContainerGenerator.ContainerFromIndex(gridItems.SelectedIndex), "gridDetails") as DataGrid;
        //    if (g != null && g.Items.Count > 0)
        //    {
        //        List<DataGridCell> cells = GetChildren<DataGridCell>((UIElement)g.ItemContainerGenerator.ContainerFromIndex(g.Items.Count - 1));
        //        if (cells.Count > 0)
        //        {
        //            cells[0].IsEditing = true;
        //            cells[0].Focus();
        //        }
        //    }
        //}


        public static FrameworkElement GetDescendantByName(FrameworkElement parent, string name)
        {
            int count = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < count; i++)
            {
                FrameworkElement child = VisualTreeHelper.GetChild(parent, i) as FrameworkElement;
                if (child != null)
                {
                    if (child.Name == name)
                        return child;

                    child = GetDescendantByName(child, name);
                    if (child != null)
                        return child;
                }
            }
            return null;
        }

        public static List<T> GetChildren<T>(UIElement parent) where T : UIElement
        {
            if (parent == null)
                return new List<T>();
            List<T> list = new List<T>();
            int count = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < count; i++)
            {
                UIElement child = VisualTreeHelper.GetChild(parent, i) as UIElement;
                if (child != null)
                {
                    if (child is T)
                        list.Add(child as T);

                    List<T> l1 = GetChildren<T>(child);
                    foreach (T u in l1)
                        list.Add(u);
                }
            }
            return list;
        }

        static T FindVisualParent<T>(UIElement element) where T : UIElement
        {
            UIElement parent = element;
            while (parent != null)
            {
                T correctlyTyped = parent as T;
                if (correctlyTyped != null)
                {
                    return correctlyTyped;
                }

                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }
            return null;
        }
        
        private void btnMarkAllPackaged_Click(object sender, RoutedEventArgs e)
        {
            foreach (tblInventoryTransaction inventoryTransaction in _inventoryTransactions)
                inventoryTransaction.Added = inventoryTransaction.NegQty;
            CheckPackage();
        }

        private bool CheckPackage()
        {
            bool allFilled = true;
            foreach (tblInventoryTransaction inventoryTransaction in _inventoryTransactions)
            {
                if (inventoryTransaction.Added < inventoryTransaction.NegQty)
                    allFilled = false;
                // Check to be sure that defined user defined fields are filled in.
                foreach (tblInventoryTransactionDetail detail in inventoryTransaction.InventoryTransactionDetails)
                {
                    foreach(tblMiscDef miscDef in _miscDefs)
                        allFilled &= (miscDef.FieldNumber == 1) ? (detail.UserDefined1 != null) :
                            (miscDef.FieldNumber == 2) ? (detail.UserDefined2 != null) :
                            (miscDef.FieldNumber == 3) ? (detail.UserDefined3 != null) :
                            (miscDef.FieldNumber == 4) ? (detail.UserDefined4 != null) :
                            true;
                }
            }

            if (allFilled)
            {
                foreach (tblInventoryTransaction inventoryTransaction in _inventoryTransactions)
                    inventoryTransaction.InventoryTransactionStatusCode = "K";
                _sme.SaveChanges();

                HasPackage = false;
                txtPackageID.Text = string.Empty;
                txtPackageID.Focus();
                _inventoryTransactions = null;
                gridItems.ItemsSource = null;
                return true;
            }

            return false;
        }

        private void btnProcess_Click(object sender, RoutedEventArgs e)
        {
            if (HasPackage)
                txtItem_LostFocus(this, null);
            else
                txtPackageID_LostFocus(this, null);
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            _closing = true;
        }

        private void gridDetails_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            if (e.Column.Header.ToString().StartsWith("UserDefined"))
            {
                IEnumerable<tblMiscDef> miscDef = _miscDefs.Where(c => c.FieldNumber == Int32.Parse(e.Column.Header.ToString().Substring(11)));
                if (miscDef.Count() > 0)
                    e.Column.Header = miscDef.First().Name;
                else
                    e.Cancel = true;
            }
            else
                e.Cancel = true;
        }


        private void gridDetails_GotFocus(object sender, RoutedEventArgs e)
        {
            if (e.OriginalSource is DataGridCell)
            {
                ((DataGridCell)e.OriginalSource).IsEditing = true;
            }
        }

        private delegate void DataGridCellFocusDelegate(DataGridCell cell);

        private void DataGridCellFocus(DataGridCell cell)
        {
            List<TextBox> textBlocks = GetChildren<TextBox>(cell);
            if (textBlocks.Count > 0)
            {
                if (!textBlocks[0].IsFocused)
                    textBlocks[0].Focus();
            }
        }

        void DataGridCell_GotFocus(object sender, RoutedEventArgs e)
        {
            // Wait for the DataGridCell to finish processing focus and then set the focus into the textbox.
            Dispatcher.BeginInvoke(new DataGridCellFocusDelegate(DataGridCellFocus), System.Windows.Threading.DispatcherPriority.Background, new object[] { (DataGridCell)sender });
        }

        private delegate void GridDetailsLoadingDelegate(DataGridRow row);

        private void GridDetailsLoading(DataGridRow row)
        {
            DataGrid grid = FindVisualParent<DataGrid>(row);
            List<DataGridCell> gridCells = GetChildren<DataGridCell>((FrameworkElement)grid.ItemContainerGenerator.ContainerFromItem(row.DataContext));
            if (gridCells.Count > 0)
            {
                gridCells[0].Focus();
                grid.BeginEdit();
            }
        }

        // Dispatch GridDetailsLoading to set the focus into the first cell when a row loads.
        private void gridDetails_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            Dispatcher.BeginInvoke(new GridDetailsLoadingDelegate(GridDetailsLoading), System.Windows.Threading.DispatcherPriority.Background, new object[] { e.Row });
        }

        private void gridDetails_LostFocus(object sender, RoutedEventArgs e)
        {
            CheckPackage();
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            HasPackage = false;
            txtPackageID.Text = string.Empty;
            txtPackageID.Focus();
            _inventoryTransactions = null;
            gridItems.ItemsSource = null;
        }
    }
}
